package com.enation.app.javashop.core.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.util.StringUtil;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import feign.Response;
import feign.Util;
import feign.codec.ErrorDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;

import java.io.IOException;
import java.lang.reflect.Type;

/**
 * feign 配置类
 * 提供ErrorDecoder的自定义：解析异常，如果是业务异常（有code有message）则转换成ServiceException
 * 以便FallbackFactory解析拦截
 * @author kingapex
 * @version 1.0
 * @data 2022/5/27 22:25
 **/
public class FeignConfiguration {
    @Bean
    public ErrorDecoder errorDecoder() {
        return new UserErrorDecoder();
    }
    /**
     * Custom ell
     * rror
     */
    public class UserErrorDecoder implements ErrorDecoder {
        private Logger logger = LoggerFactory.getLogger(getClass());
        @Override
        public Exception decode(String methodKey, Response response) {

                //如果为空，肯定不是service excetion
                if (response.body() != null) {
                    try {
                        String bodyStr  = Util.toString(response.body().asReader(Util.UTF_8));

                        if (logger.isDebugEnabled()) {
                            logger.debug("feign调用发现异常：");
                            logger.debug(bodyStr);
                        }

                        JSONObject jsonObject = JSON.parseObject(bodyStr);

                        //有code有message都不为空，判定为业务异常
                        String code = jsonObject.getString("code");
                        String message = jsonObject.getString("message");

                        if (!StringUtil.isEmpty(code) && !StringUtil.isEmpty(message)) {
                            ServiceException exception = new ServiceException(code, message);
                            return exception;
                        }

                    } catch (IOException e) {
                        e.printStackTrace();
                        return e;
                    }

                }

                //兜底：逻辑都不符合，按default返回
                return new ErrorDecoder.Default().decode(methodKey, response);


        }
    }

    public static <T> T jsonToobj(String jsonStr, Type targetType) {
        try {
            JavaType javaType = TypeFactory.defaultInstance().constructType(targetType);
            ObjectMapper mapper = new ObjectMapper();
            return mapper.readValue(jsonStr, javaType);
        } catch (IOException e) {
            throw new IllegalArgumentException("Feign JSON转换为对象异常:" + jsonStr, e);
        }
    }
}
